// +build windows

package utils

import (
	"errors"
	"fmt"
	"gitee.com/hakwolf/taibak/internal/modules/logger"
	_ "github.com/denisenkom/go-mssqldb"
	"github.com/ouqiang/goutil"

	pb "gitee.com/hakwolf/taibak/internal/modules/rpc/proto"
	//_ "github.com/go-sql-driver/mysql"
	_ "github.com/go-xorm/core"
	_ "github.com/lib/pq"
	_ "github.com/mattn/go-adodb"
	_ "github.com/mattn/go-sqlite3"
	"golang.org/x/net/context"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"syscall"
	"time"
)

type Result struct {
	output string
	err    error
}

// 执行shell命令，可设置执行超时时间
func ExecShell(ctx context.Context, command string) (string, error) {
	cmd := exec.Command("cmd", "/C", command)
	// 隐藏cmd窗口
	cmd.SysProcAttr = &syscall.SysProcAttr{
		HideWindow: true,
	}
	var resultChan chan Result = make(chan Result)
	go func() {
		output, err := cmd.CombinedOutput()
		resultChan <- Result{string(output), err}
	}()
	select {
	case <-ctx.Done():
		if cmd.Process.Pid > 0 {
			exec.Command("taskkill", "/F", "/T", "/PID", strconv.Itoa(cmd.Process.Pid)).Run()
			cmd.Process.Kill()
		}
		return "", errors.New("timeout killed")
	case result := <-resultChan:
		return ConvertEncoding(result.output), result.err
	}
}

func ConvertEncoding(outputGBK string) string {
	// windows平台编码为gbk，需转换为utf8才能入库
	outputUTF8, ok := GBK2UTF8(outputGBK)
	if ok {
		return outputUTF8
	}

	return outputGBK
}

func ExecDb(ctx context.Context, req *DbTaskRequest) (err error) { //req *pb.DbTaskRequest
	/*	dsn := getDbEngineDSN(req)
		strEngine := ""*/

	/*	engine, err := xorm.NewEngine(strEngine, dsn)
		if err != nil {
			logger.Fatal("创建xorm引擎失败", err)
		}*/
	//engine.SetMaxIdleConns(app.Setting.Db.MaxIdleConns)
	//engine.SetMaxOpenConns(app.Setting.Db.MaxOpenConns)
	baklocal := ""
	bakdir := ""
	/*	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
		if err != nil {
			log.Fatal(err)
		}*/

	AppDir, err := goutil.WorkDir()
	if err != nil {
		logger.Fatal(err)
	}
	databak := filepath.Join(AppDir, "/databak")

	fmt.Println(AppDir)
	t := time.Now() //2019-07-31 13:55:21.3410012 +0800 CST m=+0.006015601
	bakname := t.Format("20060102150405")
	fmt.Println(bakname)
	sep := string(os.PathSeparator)
	var fileEXT string
	var filename string
	var sqlDir string
	if req.Local == "" {
		switch req.Dtype {
		case SqlsT:
			{
				sqlDir = filepath.Join(databak, "/sqlserver")
			}
		case MysqlT:
			{
				sqlDir = filepath.Join(databak, "/mysql")
			}

		}
		CreateDirIfNotExists(databak, sqlDir)
		bakdir = sqlDir
	} else {
		bakdir = req.Local

	}
	var sql string
	switch req.Dtype {
	case SqlsT:
		{
			fileEXT = ".bak"
			filename = bakname + req.Dbname + fileEXT
			baklocal = bakdir + sep + filename
			sql = "BACKUP DATABASE " + req.Dbname + " TO DISK = " + "'" + baklocal + "'" + " WITH COMPRESSION, INIT, STATS = 10;"//STATS = 5
			fmt.Println(sql)
			err = EXECadodbsql(req, sql)
			break

		}
	case MysqlT:
		{
			fileEXT = ".sql"
			filename = bakname + req.Dbname + fileEXT
			baklocal = bakdir + sep + filename
			var sqlpath string
			if req.Sqlpath == "-" {
				sqlpath = "mysqldump"
			} else {
				sqlpath = req.Sqlpath + sep + "mysqldump"
			}
			err, _ = BackupMySqlDb(req, sqlpath, baklocal)
		}

	}

	return err

}

func ExecDb2(ctx context.Context, req *pb.DbTaskRequest) (err error) {
	/*	dsn := getDbEngineDSN(req)
		strEngine := ""*/

	/*	engine, err := xorm.NewEngine(strEngine, dsn)
		if err != nil {
			logger.Fatal("创建xorm引擎失败", err)
		}*/
	//engine.SetMaxIdleConns(app.Setting.Db.MaxIdleConns)
	//engine.SetMaxOpenConns(app.Setting.Db.MaxOpenConns)
	baklocal := ""
	bakdir := ""
	/*	dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
		if err != nil {
			log.Fatal(err)
		}*/

	AppDir, err := goutil.WorkDir()
	if err != nil {
		logger.Fatal(err)
	}
	databak := filepath.Join(AppDir, "/databak")

	fmt.Println(AppDir)
	t := time.Now() //2019-07-31 13:55:21.3410012 +0800 CST m=+0.006015601
	bakname := t.Format("20060102150405")
	fmt.Println(bakname)
	sep := string(os.PathSeparator)
	var fileEXT string
	var filename string
	var sqlDir string
	if req.Local == "" {
		switch req.Dtype {
		case SqlsT:
			{
				sqlDir = filepath.Join(databak, "/sqlserver")
			}
		case MysqlT:
			{
				sqlDir = filepath.Join(databak, "/mysql")
			}

		}
		CreateDirIfNotExists(databak, sqlDir)
		bakdir = sqlDir
	} else {
		bakdir = req.Local

	}
	var sql string
	switch req.Dtype {
	case SqlsT:
		{
			fileEXT = ".bak"
			filename = bakname + req.Dbname + fileEXT
			baklocal = bakdir + sep + filename
			sql = "BACKUP DATABASE " + req.Dbname + " TO DISK = " + "'" + baklocal + "'" + " WITH COMPRESSION, INIT, STATS = 5;"
			fmt.Println(sql)
			err = EXECadodbsql2(req, sql)
			break

		}
	case MysqlT:
		{
			fileEXT = ".sql"
			filename = bakname + req.Dbname + fileEXT
			baklocal = bakdir + sep + filename
			var sqlpath string
			if req.Sqlpath == "-" {
				sqlpath = "mysqldump"
			} else {
				sqlpath = req.Sqlpath + sep + "mysqldump"
			}
			err, _ = BackupMySqlDb2(req, sqlpath, baklocal)
		}

	}

	return err

}

// 获取数据库引擎DSN  mysql,sqlite,postgres
func getDbEngineDSN(req *pb.DbTaskRequest) string {
	//engine := strings.ToLower(setting.Db.Engine)
	dsn := ""
	if req.Dtype == SqlsT {
		//dsn = fmt.Sprintf("user=%s password=%s host=%s port=%d dbname=%s sslmode=disable",
		var dataSource string
		if req.Port != 0 {
			strInt64 := strconv.FormatInt(req.Port, 10)
			id16, _ := strconv.Atoi(strInt64)
			dataSource = req.Dip + "," + strconv.Itoa(id16) //setting.Db.Host
		} else {
			dataSource = req.Dip
		}
		db := Mssql{
			DataSource: dataSource,
			Database:   req.Dbname,
			// windwos: true 为windows身份验证，false 必须设置sa账号和密码
			Windows: false,
			Sa: SA{
				User:   req.Ac,
				Passwd: req.Pd,
			},
		}
		dsn = db.GetDsn()
	}

	return dsn
}
